﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;
using static System.Net.Mime.MediaTypeNames;

namespace SuperKit
{
    class CombineMovie : MediaExecutor, IComparer<FileInfo> {

        // 当如果项目只有一个的时候，是执行移动还是复制。如果为True，则移动项目，否则复制项目。
        private bool moveSingle;
        private bool isCopy;
        private bool isOverride;
        private string movieName;
        private string fileName;
        // 是否对文件进行排序
        private bool isSort;
        // 是否要合并字幕文件
        private bool isSub;
        // 是否重新生成时间戳，在某些视频合并不能成功的时候使用
        private bool isGenPts;

        public CombineMovie(ArgReader arg, IExecutorOwner form, string fpath) : base(arg, form, fpath) {
            isCopy = arg.IsContain("-copy");
            isOverride = arg.IsContain("-override");
            moveSingle = arg.IsContain("moveSingle");
            isSort = arg.IsContain("-sort");
            isSub = arg.IsContain("-sub");
            isGenPts = arg.IsContain("-genpts");
        }

        public override void Execute() {
            base.Execute();

            autoPickExtension();

            movieName = string.Format(FilePath + ext);
            if (isOverride == false && File.Exists(movieName)) {                
                Flush("Combine Moive Failed Because Exist:{0}", movieName);
                return;
            }

            fileName = string.Format(FilePath + ".txt");
            Flush("Movie:{0}", movieName);
            Flush("Text:{0}", fileName);

            StringBuilder sb = new StringBuilder();
            var info = new DirectoryInfo(FilePath);
            var files = info.GetFiles();
            if (isSort) {
                Sort(files);
            }

            int count = 0;
            FileInfo last = null;
            foreach (var i in files) {
                if (Kit.IsFileType(i, ext)) {
                    sb.Append(string.Format("file '{0}'\r\n", i.FullName));
                    last = i;
                    count++;
                }
            }

            // 当只有一个项目的时候，不合并，直接移动。
            if (count == 1) {
                if (moveSingle) {
                    File.Move(last.FullName, movieName);
                } else {
                    File.Copy(last.FullName, movieName);
                }
                End();
                return;
            }

            File.WriteAllText(fileName, sb.ToString());

            string cmd;
            if (isCopy) {
                cmd = GetCopy();
            } else {
                cmd = GetGeneral();
            }

            
            //var cmd = string.Format("-f concat -safe 0 -i \"{0}\" -vcodec h264  -b:v 4000K -b:a 128k \"{1}\"", fileName, movieName);
            Flush("Cmd:\"{0}\" {1}", ShellKit.FFMpegExe, cmd);
            ShellKit.ExecuteFFMpeg(cmd);

            File.Delete(fileName);

            End();
        }

        private void Sort(FileInfo[] files) {
            Array.Sort(files, this);
        }

        int IComparer<FileInfo>.Compare(FileInfo? x, FileInfo? y) {
            return string.Compare(x.Name, y.Name);
        }

        private void autoPickExtension() {
            if (Kit.IsEmpty(ext) == false) {
                return;
            }

            DirectoryInfo dir = new DirectoryInfo(FilePath);
            var files = dir.GetFiles();
            if (files.Length > 0) {
                ext = Path.GetExtension(files[0].Name);
                return;
            }

            ext = ".mp4";
        }


        private string GetGeneral() {
            string cmd = $"-f concat -safe 0 -i \"{fileName}\" {SizeStr} {ByteStr} -y \"{movieName}\"";
            if (gpu) {
                cmd = $"-f concat -safe 0 -i \"{fileName}\" -c:v libx264 {SizeStr} {ByteStr} -y \"{movieName}\"";
            }
            return cmd;
        }

        private string GetCopy() {
            var ptsStr = isGenPts ? "-fflags +genpts" : "";
            var subStr = isSub ? "-c:s mov_text" : "";
            var cmd = string.Format("-f concat -safe 0 {3} -i \"{0}\" -c copy {1} \"{2}\"",
                fileName, subStr, movieName, ptsStr);
            return cmd;
        }

    }
}
